Skip to content

Conversation

@Jerry-Jinfeng-Guo
Copy link
Member

@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo commented Nov 26, 2025

Closes #338

In this PR:

  • Logic to handle optional_extra
  • Documentation
  • Test

Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo self-assigned this Nov 26, 2025
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo added the feature New feature or request label Nov 26, 2025
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo changed the title logic to handle optional_extra Logic to handle optional_extra in Vision Excel converter input Nov 26, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements logic to handle optional extra columns in the tabular converter, addressing issue #338. The feature allows specifying columns that should be included in extra_info if present but won't cause conversion failure if missing.

Key Changes:

  • Added allow_missing parameter throughout the column definition parsing chain to support optional columns
  • Implemented optional_extra wrapper in column definitions to mark columns as optional
  • Enhanced error handling to gracefully skip missing optional columns while preserving required column behavior

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/power_grid_model_io/converters/tabular_converter.py Core implementation of optional_extra logic with allow_missing parameter propagation and empty DataFrame handling for missing columns
tests/unit/converters/test_tabular_converter.py Comprehensive test coverage for optional_extra feature including edge cases and integration tests
docs/converters/vision_converter.md Documentation explaining optional_extra syntax, behavior, and use cases for Vision Excel exports

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Jerry-Jinfeng-Guo and others added 3 commits November 26, 2025 12:08
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Jerry-Jinfeng-Guo and others added 4 commits November 27, 2025 14:35
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Comment on lines +68 to +71
extra:
- ID # Required - fails if missing
- Name # Required - fails if missing
- optional_extra:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if an element is specified in both the required and optional?

      extra:
        - ID            # Required - fails if missing
        - optional_extra:
          - ID          # Optional - skipped if missing

I believe that the default should be that required precedes optional, so maybe we need to add an explicit test case for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 399 to 408
allow_missing: bool = False,
) -> pd.DataFrame:
"""Interpret the column definition and extract/convert/create the data as a pandas DataFrame.
Args:
data: TabularData:
table: str:
col_def: Any:
extra_info: Optional[ExtraInfo]:
allow_missing: bool: If True, missing columns will return empty DataFrame instead of raising KeyError
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this is the right solution. If I understand correctly, this parameter is needed due to the recursion, right? Would there be a world in which either no recursion is needed, or in which we can do without this allow_missing? It feels bugprone

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 399 to 408
allow_missing: bool = False,
) -> pd.DataFrame:
"""Interpret the column definition and extract/convert/create the data as a pandas DataFrame.
Args:
data: TabularData:
table: str:
col_def: Any:
extra_info: Optional[ExtraInfo]:
allow_missing: bool: If True, missing columns will return empty DataFrame instead of raising KeyError
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add allow_missing to the tests (either by testing that it works as intended + that all sub-calls to the mocks are made correctly, and/or by raising an error if it is set but recursion level is not 0)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

col_def: Any,
table_mask: Optional[np.ndarray],
extra_info: Optional[ExtraInfo],
allow_missing: bool = False,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make a keyword arg

Suggested change
allow_missing: bool = False,
*,
allow_missing: bool = False,

optionally, you can even demand that the other fields are keyword args as well (that's OK because it's a protected member function so we can change the interface without any issues)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a private function and we can change it at will. Does it really matter if we have allow_missing as kwarg? It is a matter of preference? Is it best practice? Or is there other reason? I don't have a strong opinion, but I wish to understand better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reason is that it's very bugprone unless we thoroughly test this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a test that check the behavior when an attribute is added to both extra and optional_extra, e.g.

extra:
  - ID
  - optional_extra:
    - ID

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

col_def: Any,
table_mask: Optional[np.ndarray],
extra_info: Optional[ExtraInfo],
allow_missing: bool = False,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a private function and we can change it at will. Does it really matter if we have allow_missing as kwarg? It is a matter of preference? Is it best practice? Or is there other reason? I don't have a strong opinion, but I wish to understand better.

Comment on lines +426 to +428
return self._parse_col_def_composite(
data=data, table=table, col_def=optional_cols, table_mask=table_mask, allow_missing=True
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place where I see allow_missing=True. Why is that? Is it because it's only relevant when the underlying structure is a dict, hence then is only when the "new" extra optional parameters matter? Why isn't it relevant bellow when we have a list instead?

I don't think I've ever worked in this repo, so genuinely asking. I'd appreciate tech review over this :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now only optional_extra are fields we attribute the 'optional' to its existence.

Jerry-Jinfeng-Guo and others added 3 commits December 1, 2025 21:09
Comments from Martijn

Co-authored-by: Martijn Govers <martijn.govers@alliander.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Comments from Martijn

Co-authored-by: Martijn Govers <martijn.govers@alliander.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 1, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Graceful Handling of Missing Extra Columns in Vision Excel Files

4 participants